
//
// 110516 - AH - Created.
// 110517a- AH - Got adding content to work.
// 110517b- AH - Populate also names for Forest and Mine.
// 110517c- AH - Delete implemented.
// 120128 - AH - (Garage) Support for new ontology ProductTable.
// 120129 - AH - (Midtun) Uses new ToolTipComboBox.
//

package org.soekrat.gui.swing.pit;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

import org.soekrat.engine.Soekrat2Engine;
import org.soekrat.engine.forest.Forest;
import org.soekrat.engine.forest.GetNamesTreeVisitor;
import org.soekrat.engine.mine.Mine;
import org.soekrat.engine.mine.Resource;
import org.soekrat.engine.network.Network;
import org.soekrat.engine.network.NetworkNode;
import org.soekrat.engine.ontology.ptable.Product;
import org.soekrat.engine.ontology.ptable.ProductTable;
import org.soekrat.engine.pit.Content;
import org.soekrat.engine.pit.Node;
import org.soekrat.engine.pit.Pit;
import org.soekrat.gui.swing.tools.ToolTipComboBox;

/**
 * <p>
 *   Editor to add and remove content to nodes in the
 *   {@link Pit}.
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC) 
 */
@SuppressWarnings("serial")
public final class PitEditor extends JPanel
{
  private final Soekrat2Engine m_engine;
  
  private final Pit m_pit;
  
  private final CTM m_tmodel=new CTM();
  
  private final JComboBox m_ontologies=new ToolTipComboBox(200);
  
  private final JComboBox m_nodes=new ToolTipComboBox(200);
  
  private final JTable m_table;
  
  /**
   * <p>
   *   Constructor.
   * </p>
   * @param engine {@link Soekrat2Engine} interfaced.
   */
  public PitEditor(Soekrat2Engine engine)
  {
    if (engine==null)
    {
      throw new NullPointerException("engine");
    }
    
    m_engine=engine;
    
    m_pit=engine.getPit();
    
    setLayout(new BorderLayout());
    
    m_ontologies.addItem("forest");
    m_ontologies.addItem("mine");
    m_ontologies.addItem("network");
    m_ontologies.addItem("product-table");
    
    Box north=new Box(BoxLayout.X_AXIS);
    north.add(new JLabel("Ontology: "));
    north.add(m_ontologies);
    north.add(new JLabel("  Name: "));
    north.add(m_nodes);
    add(north, BorderLayout.NORTH);
    
    m_table=new JTable(m_tmodel);
    add(new JScrollPane(m_table), BorderLayout.CENTER);
    
    JPanel buttons=new JPanel(new FlowLayout(FlowLayout.CENTER));
    
    buttons.add
    (
      new JButton
      (
        new AbstractAction("Add") 
        {
          public void actionPerformed(ActionEvent e)
          {
            String name=getSelectedNode();
            String ontology=getSelectedOntology();
            if (name!=null && ontology!=null)
            {
              Node node=m_pit.getNode(name);
              if (node!=null)
              {
                String txt=JOptionPane.showInputDialog("URL");
                if (txt!=null)
                {
                  Content c=new Content(txt);
                  c.addOntology(ontology);
                  node.addContent(c);
                  refreshTable();
                }
              }
            }
          }
        }
      )
    );
    buttons.add
    (
      new JButton
      (
        new AbstractAction("Delete") 
        {
          public void actionPerformed(ActionEvent e)
          {
            int row=m_table.getSelectedRow();
            if (row!=-1)
            {
              String name=getSelectedNode();
              String ontology=getSelectedOntology();
              if (name!=null && ontology!=null)
              {
                Content content=m_tmodel.get(row);
                content.removeOntology(ontology);
                refreshTable();
              }
            }
          }
        }
      )
    );
    
    add(buttons, BorderLayout.SOUTH);
    
    // Do listener stuff.
    
    m_ontologies.addItemListener
    (
      new ItemListener() 
      {
        public void itemStateChanged(ItemEvent e) 
        {
          init();
        }
      }  
    );
    
    m_nodes.addItemListener
    (
      new ItemListener() 
      {
        public void itemStateChanged(ItemEvent e) 
        { 
          Object selected=m_nodes.getSelectedItem();
          if (selected!=null)
          {
            String name=selected.toString();
            
            String ontology=getSelectedOntology();
            if (ontology!=null)
            {
              Node node=m_pit.getNode(name);
              Content[] content=node.getContent(ontology);
              m_tmodel.clear();
              m_tmodel.add(content);
              m_tmodel.fireTableDataChanged();
            }
          }
        }
      }
    );
    
    // Initial population.
    init();
  }
  
  private void init()
  {
    String ontology=getSelectedOntology();
    if (ontology!=null)
    {
      if (ontology.equals("forest"))
      {
        Set<String> names=getAllForestNames();
        populateNames(names);
      }
      else if (ontology.equals("mine"))
      {
        Set<String> names=getAllMineNames();
        populateNames(names);
      }
      else if (ontology.equals("network"))
      {
        Set<String> names=getAllNetworkNames();
        populateNames(names);
      }
      else if (ontology.equals("product-table"))
      {
        Set<String> names=getAllProductTableNames();
        populateNames(names);
      }
    }
    
    refreshTable();
  }
  
  private String getSelectedNode()
  {
    Object selected=m_nodes.getSelectedItem();
    return selected==null ? null : selected.toString();
  }
  
  private String getSelectedOntology()
  {
    Object selected=m_ontologies.getSelectedItem();
    return selected==null ? null : selected.toString();
  }
  
  private void populateNames(Set<String> names)
  {
    m_nodes.removeAllItems();
    for (String name : names)
    {
      m_nodes.addItem(name);  
    }
  }
  
  private Set<String> getAllForestNames()
  {
    Forest forest=m_engine.getWheel().getForest();
    GetNamesTreeVisitor gntv=new GetNamesTreeVisitor();
    forest.dfs(gntv);
    return gntv.getSet();
  }
  
  private Set<String> getAllMineNames()
  {
    Set<String> retVal=new TreeSet<String>();
    
    Mine mine=m_engine.getWheel().getMine();
    for (Resource resource : mine)
    {
      retVal.add(resource.getName());
    }
    
    return retVal;
  }
  
  private Set<String> getAllNetworkNames()
  {
    Set<String> retVal=new TreeSet<String>();
    
    Network network=m_engine.getWheel().getNetwork();
    for (NetworkNode curr : network) 
    {
      retVal.add(curr.getName());
    }
    
    return retVal;
  }
  
  private Set<String> getAllProductTableNames()
  {
    Set<String> retVal=new TreeSet<String>();
    
    ProductTable pt=m_engine.getWheel().getProductTable();
    for (Product curr : pt) 
    {
      retVal.add(curr.getSoekratName().toString());
    }
    
    return retVal;
  }
  
  /**
   * <p>
   *   Refresh table.
   * </p>
   */
  private void refreshTable()
  {
    String name=getSelectedNode();
    String ontology=getSelectedOntology();
    if (name!=null && ontology!=null)
    {
      Node node=m_pit.getNode(name);
      Content[] content=node.getContent(ontology);
      m_tmodel.clear();
      m_tmodel.add(content);
      m_tmodel.fireTableDataChanged();
    }
  }
  
  /**
   * <p>
   *   {@link TableModel} used to show
   *   {@link Content} in a 
   *   {@link JTable}.
   * </p>
   * @author Arne Halvorsen (AH)
   * @author Laetitia Le Chatton (LLC) 
   */
  private static final class CTM extends AbstractTableModel
  {
    private List<Content> m_content=new ArrayList<Content>();
    
    void clear(){ m_content.clear(); }
    
    /**
     * <p>
     *   Adds row.
     * </p>
     * @param c {@link Content} row display.
     */
    void add(Content[] c)
    {
      for (Content curr : c) 
      {
        m_content.add(curr);  
      }
    }
    
    /**
     * <p>
     *   Gets 
     *   {@link Content} in a given row.
     * </p>
     * @param row Row's index.
     * @return {@link Content}.
     * @throws IndexOutOfBoundsException If {@code row<0 || row>=getRowCount()}.
     */
    Content get(int row){ return m_content.get(row); }
    
    // Specified in TableModel.
    public String getColumnName(int col)
    {
      switch (col)
      {
        case 0 : return "Content"; 
        default : throw new Error();
      }
    }

    // Specified in TableModel.
    public int getColumnCount(){ return 1; }

    // Specified in TableModel.
    public int getRowCount(){ return m_content.size(); }

    // Specified in TableModel.
    public Object getValueAt(int row, int col)
    {
      Content c=m_content.get(row);
      switch (col)
      {
        case 0 : return c.getText(); 
        default : throw new Error();
      }
    }
    
  }
  
}
